//////////////////////////////////////////////////////////////////////
////                                                              ////
////  CPLDController.v                                            ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pice E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Pico Computing, INC.                     ////
//// http://www.picocomputing.com                                 ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF

//This module controls the TurboLoader

//A Peekaboo is what happends when the host request the address of the last byte loaded from flash by the TurboLoader

`include "PicoDefines.v"

module CPLDController(CFClock, AttribRead, AttribWrite, MemRead, MemAddress, DataIn, DataOut, FLASH_AIN, FLASH_TRIS_A, CPLD_PEEKABOO_CF, CPLD_PEEKABOO_PPC, CPLD_RELOAD_CF);

input CFClock;                                             //200 MHz Free Running Clock
input AttribRead;                                          //Attribute Read from Card
input AttribWrite;                                         //Attribute Write to Card
input MemRead;                                             //Memory Read (Used to detect flash reads)
input [31:1]MemAddress;                                    //Memory MemAddress bus
input [15:0]DataIn;                                        //Data in from Host
output [15:0]DataOut;                                      //Data out to Host
input [25:0]FLASH_AIN;                                     //Flash MemAddress Input
output FLASH_TRIS_A;                                       //Flash Tristate Control
output CPLD_PEEKABOO_CF;                                   //This control line is used to obtain the last address used before the FPGA successfully loaded
output CPLD_RELOAD_CF;                                     //Asserting this signal causes the CPLD to reload the FPGA from the address that is currently on the address lines
input  CPLD_PEEKABOO_PPC;                                  //from PPCsystem when PPC wants to get peekaboo value.

reg ArmReload;                                             //Asserting this register will cause the PICO to reboot on the next falling edge of a ROM access

//synthesis attribute KEEP of ArmReload is TRUE;
//synthesis attribute INIT of ArmReload is "0";

wire [7:0]DataOutPeekabooLLSBs;
wire [7:0]DataOutPeekabooLMSBs;
wire [7:0]DataOutPeekabooMLSBs;
wire [7:0]DataOutPeekabooMMSBs;
wire [7:0]DataOutArmStatus;
wire AttribReadBUF;
wire MemReadBUF;
wire FlashAccess;

BUF AttribReadBuffer(.I(AttribRead), .O(AttribReadBUF));                                 //Pick AttribRead off the Global Clock Distribution Bus
BUF MemReadBuffer(.I(MemRead), .O(MemReadBUF));

//synthesis attribute KEEP of MemReadBUF is TRUE;

assign FlashAccess = (~(|MemAddress[31:26]));                                            //This signal goes high during Flash memory reads (Since the flash is located in the lower address space we assume the flash is being accessed if the MSBs on the address bus are 0.

wire ReloadEnable;
wire ArmStatusRead;
wire PeekabooLLSBRead;
wire PeekabooLMSBRead;
wire PeekabooMLSBRead;
wire PeekabooMMSBRead;


assign ReloadEnable = (MemAddress[10:1] == `CPLD_CONTROLLER_RELOAD_ADDRESS) && (DataIn[7:0] == `CPLD_CONTROLLER_RELOAD_PASSWORD); //Reload request detection - This better not take more than 5ns or reload will never arm - if this happens put the compare in the write always statement 
assign ArmStatusRead = (MemAddress[10:1] == `CPLD_CONTROLLER_RELOAD_ADDRESS) && AttribReadBUF;
assign PeekabooLLSBRead = (MemAddress[10:1] == `CPLD_CONTROLLER_PEEKABOO_LLSB_ADDRESS) && AttribReadBUF;                                              
assign PeekabooLMSBRead = (MemAddress[10:1] == `CPLD_CONTROLLER_PEEKABOO_LMSB_ADDRESS) && AttribReadBUF;                                              
assign PeekabooMLSBRead = (MemAddress[10:1] == `CPLD_CONTROLLER_PEEKABOO_MLSB_ADDRESS) && AttribReadBUF;                                              
assign PeekabooMMSBRead = (MemAddress[10:1] == `CPLD_CONTROLLER_PEEKABOO_MMSB_ADDRESS) && AttribReadBUF;

assign CPLD_PEEKABOO_CF = (PeekabooLLSBRead) || (PeekabooLMSBRead) || (PeekabooMLSBRead) || (PeekabooMMSBRead);                           //This signal forces the Flash ROM controller to tristate it's address lines and the TurboLoader to output the last address before the FPGA loaded
assign CPLD_RELOAD_CF   = (ArmReload) && (MemReadBUF) && (FlashAccess);                      //This signal controls reloading of the FPGA

//--------------CPLD Reboot Control-----------------
always @(negedge AttribWrite) begin
	if (ReloadEnable) ArmReload <= 1;
end					  

//----------------Peekaboo Control------------------
assign DataOut[7:0] = (DataOutPeekabooLLSBs[7:0] | DataOutPeekabooLMSBs[7:0] | DataOutPeekabooMLSBs[7:0] | 
                       DataOutPeekabooMMSBs[7:0] | DataOutArmStatus[7:0]);

assign DataOut[15:8] = DataOut[7:0];

assign DataOutPeekabooLLSBs[0] = 1'b0;                                        //It takes a lot of code to decode the LSB
assign DataOutPeekabooLLSBs[7:1] = (PeekabooLLSBRead)?FLASH_AIN[6:0] : 7'b0;
assign DataOutPeekabooLMSBs[7:0] = (PeekabooLMSBRead)?FLASH_AIN[14:7] : 8'b0;
assign DataOutPeekabooMLSBs[7:0] = (PeekabooMLSBRead)?FLASH_AIN[22:15] : 8'b0;
assign DataOutPeekabooMMSBs[2:0] = (PeekabooMMSBRead)?FLASH_AIN[25:23] : 3'b0;
assign DataOutPeekabooMMSBs[7:3] = 5'b0;

//---------------Arm Status Readback----------------
assign DataOutArmStatus[7:0] = (ArmStatusRead && ArmReload)?(8'hFF) : 7'b0;   //Send out all 1's if Reload is armed for the next memory read

ShortFallingDelay ShortFallingDelay(.Clock(CFClock), .In(CPLD_PEEKABOO_CF | CPLD_PEEKABOO_PPC), .Out(FLASH_TRIS_A));

endmodule